home *** CD-ROM | disk | FTP | other *** search
/ Libris Britannia 4 / science library(b).zip / science library(b) / PROGRAMM / ASSEMBLE / H235A.ZIP / ASM_0_M.ZIP / KBD_FIX.ASM < prev    next >
Assembly Source File  |  1984-01-28  |  13KB  |  266 lines

  1. ;------------------------------------------------------------------------------;
  2. ;  KBD_FIX.COM  from Socha's Toolbox by John Socha                             ;
  3. ;    Ref: Softalk PC Nov 83 pg 117                                             ;
  4. ;         Softalk PC Jan 84 pg 107  (corrections, incorporated below)          ;
  5. ;                                                                              ;
  6. ; Note that type ahead buffer can be cleared by pressing Alt and Ctrl together.;
  7. ;------------------------------------------------------------------------------;
  8. VECTORS                 SEGMENT         AT 0H
  9.         ORG             9H*4
  10. KEYBOARD_INT_VECTOR                     LABEL           DWORD
  11.         ORG             16H*4
  12. KEYBOARD_IO_VECTOR                      LABEL           DWORD
  13. VECTORS                 ENDS
  14.  
  15. ROM_BIOS_DATA           SEGMENT         AT 40H
  16.         ORG             17H
  17. KBD_FLG                 DB              ?
  18.         ORG             1AH
  19. ROM_BUFFER_HEAD         DW              ?
  20. ROM_BUFFER_TAIL         DW              ?
  21. KB_BUFFER               DW              16 DUP          (?)
  22. KB_BUFFER_END           LABEL           WORD
  23. ROM_BIOS_DATA           ENDS
  24.  
  25. CODE_SEG                SEGMENT
  26.         ASSUME          CS:CODE_SEG
  27.         ORG             100H
  28. BEGIN:  JMP             INIT_VECTORS    ;Initialize vectors and attach to DOS
  29.  
  30. ROM_KEYBOARD_INT        DD              ;Address for ROM routine
  31. ROM_KEYBOARD_IO         DD
  32. BUFFER_HEAD             DW              OFFSET KEYBOARD_BUFFER
  33. BUFFER_TAIL             DW              OFFSET KEYBOARD_BUFFER
  34. KEYBOARD_BUFFER         DW              160 DUP (0)   ;159 character buffer
  35. KEYBOARD_BUFFER_END     LABEL           WORD
  36.  
  37. ;-----------------------------------------------------------------;
  38. ; This procedure sends a short beep when the buffer fills.        ;
  39. ;-----------------------------------------------------------------;
  40.  
  41. KB_CONTROL      EQU     61H     ;Control bits for keyboard (and speaker)
  42. ERROR_BEEP      PROC    NEAR
  43.                 PUSH    AX
  44.                 PUSH    BX
  45.                 PUSH    CX
  46.                 PUSHF                   ;Save the old interrupt enable flag
  47.                 CLI                     ;Turn off beep during interrupt
  48.                 MOV     BX,30           ;Number of cycles for 1/8 second tone
  49.                 IN      AL,KB_CONTROL
  50.                 PUSH    AX
  51. START_OF_ONE_CYCLE:
  52.                 AND     AL,0FCH
  53.                 OUT     KB_CONTROL,AL
  54.                 MOV     CX,60           ;Delay for one half cycle
  55. OFF_LOOP:
  56.                 LOOP    OFF_LOOP
  57.                 OR      AL,2            ;Turn on the speaker
  58.                 OUT     KB_CONTROL,AL
  59.                 MOV     CX,60           ;Delay for second half cycle
  60. ON_LOOP:
  61.                 LOOP    ON_LOOP
  62.                 DEC     BX              ;200 cycles yet
  63.                 JNZ     START_OF_ONE_CYCLE
  64.                 POP     AX              ;Recover old keyboard information
  65.                 OUT     KB_CONTROL,AL
  66.                 POPF                    ;Restore interrupt flag
  67.                 POP     CX
  68.                 POP     BX
  69.                 POP     AX
  70.                 RET
  71. ERROR_BEEP      ENDP
  72.  
  73. ;---------------------------------------------------------------------;
  74. ;This procedure checks the ROM keyboard buffer to see if some program ;
  75. ;tried to clear this buffer.  We know it's been cleared when the ROM  ;
  76. ;tail and header overlap.  Normally, the new procedure below keep the ;
  77. ;dummy character, word 0, in the buffer.                              ;
  78. ;                                                                     ;
  79. ;Uses BX,DS                                                           ;
  80. ;Writes:        BUFFER_HEAD, BUFFER_TAIL, ROM_BUFFER_HEAD             ;
  81. ;               ROM_BUFFER_TAIL                                       ;
  82. ;Reads:         KEYBOARD_BUFFER, KB_BUFFER                            ;
  83. ;---------------------------------------------------------------------;
  84. CHECK_CLEAR_BUFFER    PROC     NEAR
  85.                 ASSUME  DS:ROM_BIOS_DATA
  86.                 MOV     BX,ROM_BIOS_DATA    ;Establish pointer to BIOS data
  87.                 MOV     DS,BX
  88.                 CLI                         ;Turn off interrupts during this check
  89.                 MOV     BX,ROM_BUFFER_HEAD  ;Check to see if buffer is cleared
  90.                 CMP     BX,ROM_BUFFER_TAIL  ;Is the buffer empty?
  91.                 JNE     BUFFER_OK           ;No, then everything is alright
  92.                                             ;Yes, then clear the internal buffer
  93.                 MOV     BX,OFFSET KB_BUFFER ;Reset the buffer with word 0 in buffer
  94.                 MOV     ROM_BUFFER_HEAD,BX
  95.                 ADD     BX,2
  96.                 MOV     ROM_BUFFER_TAIL,BX
  97.                 ASSUME  DS:CODE_SEG
  98.                 MOV     BX,CS
  99.                 MOV     DS,BX
  100.                 MOV     BX,OFFSET KEYBOARD_BUFFER  ;Reset internal buffer
  101.                 MOV     BUFFER_HEAD,BX
  102.                 MOV     BUFFER_TAIL,BX
  103. BUFFER_OK:
  104.                 ASSUME  DS:CODE_SEG
  105.                 STI                     ;Interrupts back on
  106.                 RET
  107. CHECK_CLEAR_BUFFER   ENDP
  108.  
  109. ;------------------------------------------------------------------------------;
  110. ;This procedure intercepts the keyboard interrupt and moves any new            ;
  111. ;charcters to the internal, 80 character, buffer.                              ;
  112. ;------------------------------------------------------------------------------;
  113.  
  114. INTERCEPT_KEYBOARD_INT PROC     NEAR
  115.                 ASSUME  DS:NOTHING
  116.                 PUSH    DS
  117.                 PUSH    SI
  118.                 PUSH    BX
  119.                 PUSH    AX
  120.                 CALL    CHECK_CLEAR_BUFFER   ;Check for buffer cleared
  121.                 PUSHF
  122.                 CALL    ROM_KEYBOARD_INT     ;Read scan code with BIOS routines.
  123. ;------         Transfer any charcters to internal buffer
  124.  
  125.                 ASSUME  DS:ROM_BIOS_DATA
  126.                 MOV     BX,ROM_BIOS_DATA
  127.                 MOV     DS,BX
  128.                 MOV     SI,BUFFER_TAIL
  129.                 MOV     BX,ROM_BUFFER_HEAD    ;Check if real character in buffer
  130.                 ADD     BX,2                  ;Skip over dummy character
  131.                 CMP     BX,OFFSET KB_BUFFER_END
  132.                 JB      DONT_WRAP             ;No need to wrap the pointer
  133.                 MOV     BX,OFFSET KB_BUFFER   ;Wrap the pointer
  134. DONT_WRAP:
  135.                 CMP     BX,ROM_BUFFER_TAIL    ;Is there a real character?
  136.                 JE      NO_NEW_CHARACTERS     ;No, then return to caller
  137.                 MOV     AX,[BX]          ;Yes, move character to internal buffer
  138.                 MOV     CS:[SI],AX
  139.                 ADD     SI,2                  ;Move to next position
  140.                 CMP     SI,OFFSET KEYBOARD_BUFFER_END
  141.                 JB      NOT_AT_END
  142.                 MOV     SI,OFFSET KEYBOARD_BUFFER
  143. NOT_AT_END:
  144.                 CMP     SI,BUFFER_HEAD      ;Buffer overrun?
  145.                 JNE     WRITE_TO_BUFFER     ;Yes, beef and throw out character
  146.                 CALL    ERROR_BEEP
  147.                 JMP     SHORT NOT_AT_KB_END
  148. WRITE_TO_BUFFER:
  149.                 MOV     BUFFER_TAIL,SI
  150. NOT_AT_KB_END:
  151.                 MOV     ROM_BUFFER_HEAD,BX
  152.  
  153. NO_NEW_CHARACTERS:
  154. ;---------      See if CTRL + ALT pushed and clear buffer if so
  155.  
  156.                 MOV     AL,KBD_FLG         ;Get status of shift keys into AL
  157.                 AND     AL,0CH             ;Isolate Alt and Ctrl shift flags
  158.                 CMP     AL,0CH             ;Are both the Ctrl and Alt keys down?
  159.                 JNE     DONT_CLEAR_BUFFER  ;No, then don't clear the buffer
  160.                 MOV     AX,BUFFER_TAIL     ;Yes, then clear the buffer
  161.                 MOV     BUFFER_HEAD,AX
  162.  
  163. DONT_CLEAR_BUFFER:
  164.                 POP     AX
  165.                 POP     BX
  166.                 POP     SI
  167.                 POP     DS
  168.                 IRET
  169. INTERCEPT_KEYBOARD_INT  ENDP
  170.  
  171. ;------------------------------------------------------------------------------;
  172. ;This procedure replaces the ROM BIOS routines for reading a character         ;
  173. ;------------------------------------------------------------------------------;
  174.  
  175. INTERCEPT_KEYBOARD_IO   PROC   FAR
  176.         STI                          ;Interrupts back on
  177.         PUSH    DS                   ;Save current DS
  178.         PUSH    BX                   ;Save BX temporarily
  179.         CALL    CHECK_CLEAR_BUFFER   ;Check for buffer cleared
  180.         MOV     BX,CS                ;Establish pointer to data area
  181.         MOV     DS,BX
  182.         OR      AH,AH                ;AH=0?
  183.         JZ      READ_CHARACTER       ;Yes, read a character
  184.         CMP     AH,1                 ;AH=1?      **************
  185.         JZ      READ_STATUS          ;Yes, return the status
  186.         POP     BX                   ;Let the ROM BIOS handle other functions
  187.         POP     DS
  188.         ASSUME  DS:NOTHING
  189.         JMP     ROM_KEYBOARD_IO      ;Call ROM BIOS for other functions
  190.                                      ;Read the key
  191.         ASSUME  DS:CODE_SEG
  192. READ_CHARACTER:                      ;ASCII read
  193.         STI                          ;Interrupts back on during loop
  194.         NOP                          ;Allow an interrupt to occur
  195.         CLI                          ;Interrupts back off
  196.         MOV     BX,BUFFER_HEAD       ;Get pointer to head of buffer
  197.         CMP     BX,BUFFER_TAIL       ;Test end of buffer
  198.         JE      READ_CHARACTER       ;Loop until something in buffer
  199.         MOV     AX,[BX]              ;Get scan code and ASCII code
  200.         ADD     BX,2                 ;Move to next word in buffer
  201.         CMP     BX,OFFSET KEYBOARD_BUFFER_END   ;At end of buffer?
  202.         JNE     SAVE_POINTER         ;No, continue
  203.         MOV     BX,OFFSET KEYBOARD_BUFFER  ;Yes, reset to buffer start
  204. SAVE_POINTER:
  205.         MOV     BUFFER_HEAD,BX       ;Store value in variable
  206.         POP     BX
  207.         POP     DS
  208.         IRET                         ;Return to caller
  209. ;------------ASCII status
  210.  
  211. READ_STATUS:
  212.         CLI                          ;Interrupts off
  213.         MOV     BX,BUFFER_HEAD       ;Get head pointer
  214.         CMP     BX,BUFFER_TAIL       ;If equal (ZF=1) then nothing there
  215.         MOV     AX,[BX]
  216.         STI                          ;Interrupts back on
  217.         POP     BX                   ;Recover registers
  218.         POP     DS
  219.         RET     2                    ;Throw away flags
  220. INTERCEPT_KEYBOARD_IO     ENDP
  221.  
  222. ;------------------------------------------------------------------------------;
  223. ;This procedure initializes the interrupt vectors                              ;
  224. ;------------------------------------------------------------------------------;
  225. INIT_VECTORS    PROC    NEAR
  226.         ASSUME  DS:VECTORS
  227.         PUSH    DS                      ;Save old Data Segment
  228.         MOV     AX,VECTORS              ;Set up the data segment for vectors
  229.         MOV     DS,AX
  230.         CLI                             ;Don't allow interrupts
  231.         MOV     AX,KEYBOARD_INT_VECTOR  ;Save addresses of BIOS routines
  232.         MOV     ROM_KEYBOARD_INT,AX
  233.         MOV     AX,KEYBOARD_INT_VECTOR[2]
  234.         MOV     ROM_KEYBOARD_INT[2],AX
  235.                                         ;Set up new KEYBOARD_INT vector
  236.         MOV     KEYBOARD_INT_VECTOR,OFFSET INTERCEPT_KEYBOARD_INT
  237.         MOV     KEYBOARD_INT_VECTOR[2],CS
  238.         STI                             ;Allow interrupts again
  239.                                         ;Set up keyboard IO vector
  240.         MOV     AX,KEYBOARD_IO_VECTOR
  241.         MOV     ROM_KEYBOARD_IO,AX
  242.         MOV     AX,KEYBOARD_IO_VECTOR[2]
  243.         MOV     ROM_KEYBOARD_IO[2],AX
  244.         MOV     KEYBOARD_IO_VECTOR,OFFSET INTERCEPT_KEYBOARD_IO
  245.         MOV     KEYBOARD_IO_VECTOR[2],CS
  246.                                         ;Now set up the keyboard buffer, etc.
  247.  
  248.        ASSUME  DS:ROM_BIOS_DATA
  249.         MOV     AX,ROM_BIOS_DATA
  250.         MOV     DS,AX
  251.         CLI                             ;Don't allow interrupts
  252.         MOV     BX,OFFSET KB_BUFFER
  253.         MOV     ROM_BUFFER_HEAD,BX
  254.         MOV     WORD PTR [BX],0
  255.         ADD     BX,2
  256.         MOV     ROM_BUFFER_TAIL,BX
  257.         STI                             ;Allow interrupts again
  258.  
  259.         MOV     DX,OFFSET INIT_VECTORS  ;End of resident portion
  260.         INT     27H                     ;Terminate but stay resident
  261. INIT_VECTORS    ENDP
  262.  
  263. CODE_SEG        ENDS
  264.         END     BEGIN
  265.  
  266.